package com.wsg.dep.core;


import com.wsg.dep.exception.AlertException;
import com.wsg.dep.exception.TimeoutException;
import com.wsg.dep.seq.FixedSequenceGroup;
import com.wsg.dep.seq.Sequence;
import com.wsg.dep.seq.Sequencer;

/**
 * 用于跟踪发布者的游标（cursor）以及依赖的 EventProcessor 的序列，以处理数据结构。
 */
public class ProcessingSequenceBarrier implements SequenceBarrier{

    /**
     * 等待策略
     */
    private final WaitStrategy waitStrategy;

    /**
     * 依赖的序列
     */
    private final Sequence dependentSequence;

    /**
     * 是否告警
     */
    private volatile boolean alerted = false;

    /**
     * 游标序列
     */
    private final Sequence cursorSequence;

    /**
     * 序列跟踪管理器
     */
    private final Sequencer sequencer;


    /**
     * 构造器
     * @param sequencer 序列跟踪管理器
     * @param waitStrategy 等待策略
     * @param cursorSequence 游标序列
     * @param dependentSequences 依赖的序列集合
     */
    public ProcessingSequenceBarrier(
            final Sequencer sequencer,
            final WaitStrategy waitStrategy,
            final Sequence cursorSequence,
            final Sequence[] dependentSequences)
    {
        this.sequencer = sequencer;
        this.waitStrategy = waitStrategy;
        this.cursorSequence = cursorSequence;

        // 依赖的序列为空时使用自身的游标序列
        if (0 == dependentSequences.length)
        {
            dependentSequence = cursorSequence;
        }
        else
        {
            dependentSequence = new FixedSequenceGroup(dependentSequences);
        }
    }
    
    @Override
    public long waitFor(long sequence) throws AlertException, InterruptedException, TimeoutException {
        // 检查是否告警过
        checkAlert();

        // 等待当前可用的序列
        long availableSequence = waitStrategy.waitFor(sequence, cursorSequence, dependentSequence, this);

        // 当前可用序列小于等待的序列返回可用序列
        if (availableSequence < sequence)
        {
            return availableSequence;
        }

        // 获取可以安全地从环形缓冲区读取的最高序列编号
        return sequencer.getHighestPublishedSequence(sequence, availableSequence);
    }

    @Override
    public long getCursor() {
        return dependentSequence.get();
    }

    @Override
    public boolean isAlerted() {
        return alerted;
    }

    @Override
    public void alert() {
        alerted = true;
        // 通知所有正在阻塞等待的 EventProcessor
        waitStrategy.signalAllWhenBlocking();
    }

    @Override
    public void clearAlert() {
        alerted = false;
    }

    @Override
    public void checkAlert() throws AlertException {
        if (alerted)
        {
            throw AlertException.INSTANCE;
        }
    }
}
